
import '../../../src/env'

import { assert } from "chai";
import { HttpClient, WsClient } from "tsrpc";
import { GameClient } from "../../../src/shared/gameClient/GameClient";
import { HallClient } from "../../../src/shared/hallClient/HallClient";
import { ResAuthorize } from "../../../src/shared/hallClient/protocols/PtlAuthorize";
import { ApiCryptoHelper } from "../../../src/shared/tsgfServer/apiCrypto/ApiCryptoHelper";
import { EMatchFromType, ISingleMatcherParams, IMatchResult, MatcherKeys } from "../../../src/shared/tsgf/match/Models";

export function createHallClient(hallServerUrl: string): HallClient {
    return new HallClient(hallServerUrl);
}
export function createGameClient(playerToken: string, serverUrl: string): GameClient {
    return new GameClient(serverUrl, playerToken);
}

export const hallClient = createHallClient('http://127.0.0.1:7100');

/**模拟服务端获取玩家的token*/
export async function authPlayerToken(openId: string, showName: string): Promise<ResAuthorize> {
    let req1 = ApiCryptoHelper.appCryptoEncrypt("default", "FDGWPRET345-809RGKFER43SKGF", {
        openId: openId,
        showName: showName,
        authTokenDay: 1,
    });
    const ret1 = await hallClient.client.callApi("Authorize", req1);
    assert.ok(ret1.isSucc, ret1.err?.message);
    assert.ok(ret1.res, 'res为空');
    return ret1.res!;
}

export async function requestMatchOneSingle(playerToken: string, playerId: string,
    maxPlayers: number = 8, minPlayers: number = 3): Promise<string> {
    let retM1 = await hallClient.requestMatch(playerToken, {
        matchFromType: EMatchFromType.Player,
        matchFromInfo: {
            playerIds: [playerId],
        },
        maxPlayers: maxPlayers,
        matcherKey: MatcherKeys.Single,
        matcherParams: {
            minPlayers: minPlayers,
            resultsContinueRoomJoinUsMatch: true,
        } as ISingleMatcherParams,
    });
    assert.ok(retM1.succ, retM1.err);
    let matchReqId = retM1.data!;
    return matchReqId;
}
export async function cancelMatch(playerToken: string, matchReqId: string): Promise<void> {
    let retM1 = await hallClient.cancelMatch(playerToken, matchReqId);
    assert.ok(retM1.succ, retM1.err);
}

/**查询匹配结果,要求自行延时,里面断言一定会获取到结果!*/
export async function queryMatch(playerToken: string, matchReqId: string): Promise<IMatchResult> {
    let retM1 = await hallClient.queryMatch(playerToken, matchReqId);
    assert.ok(!!retM1, "结果应该要出了,但没出！");
    assert.ok(retM1?.succ === true, retM1?.err);
    return retM1!.data!;
}

export async function authToGameServer(playerShowName: string, playerToken: string, gameServerUrl: string): Promise<GameClient> {
    let gameClient1 = createGameClient(playerToken, gameServerUrl);
    let gameRet = await gameClient1.authorize({ showName: playerShowName });
    assert.ok(gameRet.succ, gameRet.err);
    gameClient1.onRecvRoomMsg = (msg) => {
        console.log(`${playerShowName}: 收到【${msg.fromPlayerInfo.showName}】房间消息[${msg.recvType}]：${msg.msg}`);
    };
    gameClient1.onPlayerJoinRoom = (playerInfo, roomInfo) => {
        console.log(`${playerShowName}: 有玩家进入房间：${playerInfo.showName}`);
    };
    gameClient1.onPlayerLeaveRoom = (playerInfo, roomInfo) => {
        console.log(`${playerShowName}: 有玩家退出房间：${playerInfo.showName}`);
    };
    gameClient1.onDismissRoom = (roomInfo) => {
        console.log(`${playerShowName}: 房间被解散`);
    };
    return gameClient1;
}


export async function createAndEnterRoom(playerToken: string, playerId: string, playerShowName: string,
    maxPlayers: number = 4, isPrivate: boolean = false, teamId?: string,
    fixedTeamCount?: number, fixedTeamMinPlayers?: number, fixedTeamMaxPlayers?: number,
    freeTeamMinPlayers?: number, freeTeamMaxPlayers?: number)
    : Promise<{ gameClient: GameClient, roomId: string, gameServerUrl: string }> {
    let createRet = await hallClient.createRoom(playerToken, {
        roomName: '测试的房间',
        ownerPlayerId: playerId,
        maxPlayers: maxPlayers,
        isPrivate: isPrivate,

        fixedTeamCount: fixedTeamCount,
        fixedTeamMinPlayers: fixedTeamMinPlayers,
        fixedTeamMaxPlayers: fixedTeamMaxPlayers,

        freeTeamMinPlayers: freeTeamMinPlayers,
        freeTeamMaxPlayers: freeTeamMaxPlayers,
    });
    assert.ok(createRet.succ, createRet.err);
    let createData = createRet.data!;

    //连接游戏服务器
    let gameClient = await authToGameServer(playerShowName, playerToken, createData.gameServerUrl);
    //加入自己创建的房间
    let joinRet = await gameClient.joinRoom(createData.roomInfo.roomId, teamId);
    assert.ok(joinRet.succ, joinRet.err);

    return {
        gameClient: gameClient,
        roomId: createData.roomInfo.roomId,
        gameServerUrl: createData.gameServerUrl,
    };
}

/**根据房间ID认证进入游戏服务器,返回游戏客户端*/
export async function authToGameServerByRoomId(playerToken: string, roomId: string, playerShowName: string): Promise<GameClient> {
    let regRet = await hallClient.getRoomRegInfo(playerToken, roomId);
    assert.ok(regRet.succ, regRet.err);
    let gameClient = await authToGameServer(playerShowName, playerToken, regRet.data!.gameServerUrl);
    return gameClient;
}
/**直接加入房间,要求成功!*/
export async function joinRoom(playerToken: string, roomId: string, playerShowName: string, teamId?: string): Promise<GameClient> {
    let gameClient = await authToGameServerByRoomId(playerToken, roomId, playerShowName);
    let joinRet = await gameClient.joinRoom(roomId, teamId);
    assert.ok(joinRet.succ, joinRet.err);
    return gameClient;
}
/**根据指定的游戏服务器.连接并加入房间*/
export async function joinRoomUseGameServer(gameServerUrl: string, playerToken: string, roomId: string, playerShowName: string): Promise<GameClient> {
    let gameClient = await authToGameServer(playerShowName, playerToken, gameServerUrl);
    let joinRet = await gameClient.joinRoom(roomId);
    assert.ok(joinRet.succ, joinRet.err);
    return gameClient;
}